package com.zhuanzhuan.hero.user.util;

import cn.hutool.core.util.ObjectUtil;
import com.zhuanzhuan.hero.user.annotations.EncryptedField;
import com.zhuanzhuan.hero.user.annotations.EncryptedTable;
import com.zhuanzhuan.hero.user.helper.ZzUserHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @ClassName EncryptDecryptUtil
 * @Description
 * @Author hanjunjun
 * @Date 2024/7/22 17:51
 */
@Slf4j
public class EncryptDecryptUtil {

    /**
     * 判断一个对象是否需要做加解密操作
     *
     * @param object
     * @return boolean
     * @author  hanjunjun
     * @date 2024/7/22
     **/
    public static boolean needToDecrypt(Object object) {
        Class<?> objectClass = object.getClass();
        EncryptedTable sensitiveData = AnnotationUtils.findAnnotation(objectClass, EncryptedTable.class);
        return Objects.nonNull(sensitiveData);
    }

    /**
     * 对一个对象解密
     *  类上加了注解且字段有注解的把对应字段解密
     * @param result
     * @return void
     * @author  hanjunjun
     * @date 2024/7/22
     **/
    public static void objectDecrypt(Object result) throws IllegalAccessException {
        //遍历字段  有注解的字段进行解密
        Class<?> parameterObjectClass = result.getClass();
        Field[] declaredFields = parameterObjectClass.getDeclaredFields();
        for (Field field : declaredFields) {
            EncryptedField annotation = field.getAnnotation(EncryptedField.class);
            if (Objects.isNull(annotation)) {
                continue;
            }
            fieldDecrypt(field, result);
        }
    }

    private static void fieldDecrypt(Field field, Object result) throws IllegalAccessException {
        field.setAccessible(true);
        Object fieldValue = field.get(result);
        if (fieldValue instanceof String) {
            //定制String类型的解密算法
            String value = (String) fieldValue;
            // 使用try-catch捕获异常，处理数据库中未加密的数据，直接返回未加密数据
            try{
                value = ZzUserHelper.decrypt(value);
            }catch (Exception e){
                log.error("字段解密异常", e);
            }
            field.set(result, value);
        }
    }

    /**
     * 对一个对象进行加密处理
     *
     * @param parameterObject
     * @return void
     * @author  hanjunjun
     * @date 2024/7/22
     **/
    public static void objectEncrypt(Object parameterObject, boolean isStringType) throws IllegalAccessException{
        if(ObjectUtil.isEmpty(parameterObject)){
            return;
        }
        // 获取传入对象的类信息
        Class<?> parameterObjectClass = parameterObject.getClass();
        // 尝试查找该类上的@EncryptedTable注解
        EncryptedTable encryptDecryptClass = AnnotationUtils.findAnnotation(parameterObjectClass, EncryptedTable.class);
        if (Objects.isNull(encryptDecryptClass)){
            return;
        }
        // 获取类中所有声明的字段
        Field[] declaredFields = parameterObjectClass.getDeclaredFields();
        //对所有字段进行加密处理
        for (Field field : declaredFields) {
            EncryptedField annotation = field.getAnnotation(EncryptedField.class);
            if (Objects.nonNull(annotation)) {
                fieldEncrypt(field, parameterObject, isStringType);
            }
        }
    }

    private static void fieldEncrypt(Field field, Object parameterObject, boolean isStringType) throws IllegalAccessException {
        field.setAccessible(true);
        Object fieldValue = field.get(parameterObject);
        if (isStringType) {
            if (fieldValue instanceof String) {
                //定制String类型的加密算法
                String strValue = (String) fieldValue;
                field.set(parameterObject, ZzUserHelper.encrypt(strValue));
            }
        } else if ((fieldValue instanceof Collection)){
            field.set(parameterObject, listFieldEncrypt(fieldValue));
        }
    }

    public static Object listFieldEncrypt(Object fieldValue) {
        //只处理List<String>的
        if (!(fieldValue instanceof Collection)) {
            return fieldValue;
        }

        List list = (List) fieldValue;
        if (list.isEmpty() || !(list.get(0) instanceof String)) {
            return list;
        }
        Object[] array = list.toArray();
        for (int i = 0; i < array.length; i++) {
            Object item = array[i];
            array[i] = ZzUserHelper.encrypt((String)item);
        }

        return new ArrayList(Arrays.asList(array));
    }

    public static void main(String []args){


    }

}
